package pacBioSimple;



import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import tools.kmer.KmerSet_binary;

public class SlideAndMaskPacBio {
	
	String pacBioFile =null;
	String outputFile=null;
	KmerSet_binary kmerDB = null;
	
	public SlideAndMaskPacBio(String PacBioFile, KmerSet_binary kmerDB, String outputfile)
	{
		this.pacBioFile=PacBioFile;
		this.kmerDB=kmerDB;
		this.outputFile=outputfile;
	}

	public void doSlidingAndMasking()
	{
		try {
			BufferedReader br = new BufferedReader(new FileReader(pacBioFile));
			PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(outputFile)));
				
			String header="";
			String original="";
			String corrected="";
			String quality="";
			String combination="";
			while(br.ready())
			{
				String line = br.readLine();
				line=line.trim();
				if(line.startsWith(">"))
				{
					// new pacBio sequence
					//write chr
					if(corrected.length()>0)
					{
						//before writing we have to slide and mask the genome
						//System.out.println(chr);
						List<StringBuilder> maskResult=slideAndMask(corrected,quality);
						//removeIrland(maskResult);
						pw = writePacBio(header, original, corrected, quality, combination, maskResult, pw);
					}
					header=line;
					original=br.readLine();
					corrected=br.readLine();
					quality=br.readLine();
					combination=br.readLine();
				}				
			}
			List<StringBuilder> maskResult=slideAndMask(corrected,quality);
			//removeIrland(maskResult);
			pw = writePacBio(header, original, corrected, quality, combination, maskResult, pw);			
			
			pw.flush();
	
			
			pw.close();
	
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private List<StringBuilder>removeIrland(List<StringBuilder>slideOutput)
	{
		StringBuilder qualityString=slideOutput.get(1);
		StringBuilder correctedString=slideOutput.get(0);
		int counter=0;
		StringBuilder new_qualityString= new StringBuilder();
		for(int i=0; i < qualityString.length();++i)
		{
			if(qualityString.charAt(i)!='E')
			{
				++counter;
			}
			else
			{
				if(counter>this.kmerDB.getKmerSize())
				{
					new_qualityString.append(qualityString.substring(i-counter,i));
				}
				else
				{
					for(int j=0; j< counter;++j)
					{
						new_qualityString.append("E");
					}
				}
				counter=0;
			}
		}
		if(counter>0)
		{
			if(counter>this.kmerDB.getKmerSize())
			{
				new_qualityString.append(qualityString.substring(qualityString.length()-counter,qualityString.length()));
			}
			else
			{
				for(int j=0; j< counter;++j)
				{
					new_qualityString.append("E");
				}
			}
		}
		counter=0;
		StringBuilder new_corrected_String= new StringBuilder();
		for(int i=0; i < correctedString.length();++i)
		{
			if(correctedString.charAt(i)!=' ')
			{
				++counter;
			}
			else
			{
				if(counter>this.kmerDB.getKmerSize())
				{
					new_corrected_String.append(correctedString.substring(i-counter,i));
				}
				else
				{
					for(int j=0; j< counter;++j)
					{
						new_corrected_String.append(" ");
					}
				}
				counter=0;
			}
		}
		if(counter>0)
		{
			if(counter>this.kmerDB.getKmerSize())
			{
				new_corrected_String.append(correctedString.substring(correctedString.length()-counter,correctedString.length()));
			}
			else
			{
				for(int j=0; j< counter;++j)
				{
					new_corrected_String.append(" ");
				}
			}
		}
		
		slideOutput.set(0, new_corrected_String);
		slideOutput.set(1,new_qualityString);
		
		return slideOutput;
	}
	
	
	private List<StringBuilder> slideAndMask(String corrected, String qualityString)
	{
		StringBuilder masked_corrected= new StringBuilder();
		StringBuilder masked_quality= new StringBuilder();
		StringBuilder corrected_sb = new StringBuilder(corrected);

		int i=0;
		int t=0;
		//System.out.println(kmerDB.getKmerSize());
		while(i<corrected_sb.length()-this.kmerDB.getKmerSize())
		{
			
			String quality_string = qualityString.substring(t,t+this.kmerDB.getKmerSize());
			String fragment = corrected_sb.substring(i,i+this.kmerDB.getKmerSize());
			//System.out.println("1");
			//System.out.println(quality_string);
			//System.out.println(fragment);
			while(quality_string.contains("C") || quality_string.contains("T") || quality_string.contains("S") )
			{
				if(quality_string.contains("T"))
				{
					masked_quality.append(qualityString.charAt(t));
					++t;	
				}
				else
				{
					masked_quality.append(qualityString.charAt(t));
					masked_corrected.append(corrected.charAt(i));
					++i;
					++t;
				}
				
				
				if(i+this.kmerDB.getKmerSize()<=corrected_sb.length()-1)
				{
					quality_string = qualityString.substring(t,t+this.kmerDB.getKmerSize());
					fragment=corrected.substring(i,i+this.kmerDB.getKmerSize());
				}
				else
				{
					fragment=null;
					break;
				}
			}
			//now we have to check if the next kmer have been seen in the black list
			//System.out.println("fragment check");
			if(fragment != null)
			{
				int kmerVal=MyUtil.checkKmerDistribution(fragment,this.kmerDB);
				//System.out.println(kmerVal);
				if(kmerVal>0)
				{
					//masked total fragment
					for(int j=0; j < fragment.length();++j)
					{
						masked_corrected.append(" ");
						masked_quality.append("E");
						if(j>0)
						{
							++i;
							++t;
						}
					}
				}
				else
				{
					masked_corrected.append(corrected.charAt(i));	
					masked_quality.append(qualityString.charAt(t));
				}
				
				++i;
				++t;
			}
			else
			{
				//System.out.println("fragment is empty");
				break;
			}
		}
		
		String endFragment_quality = qualityString.substring(t,qualityString.length());
		String endFragment_corrected= corrected.substring(corrected.length()-this.kmerDB.getKmerSize(),corrected.length());
		if(endFragment_quality.contains("N"))
		{
			int kmerVal=MyUtil.checkKmerDistribution(endFragment_corrected,this.kmerDB);
			if(kmerVal>0)
			{
				for(int j=0; j < endFragment_corrected.length();++j)
				{
					masked_corrected.append(" ");
					masked_quality.append("E");
				}
			}
			else
			{
				
				for(int j=0; j < endFragment_corrected.length();++j)
				{
					if(j<endFragment_corrected.length() && j <endFragment_quality.length() )
					{
						masked_corrected.append(endFragment_corrected.charAt(j));	
						masked_quality.append(endFragment_quality.charAt(j));
					}
				}
			}
			if(endFragment_corrected.length()<endFragment_quality.length())
			{
				for(int l=endFragment_corrected.length(); l<endFragment_quality.length()-endFragment_corrected.length();++l)
				{
					masked_quality.append(endFragment_quality.charAt(l));
				}
			}
		}		
		List<StringBuilder> outputOfMasking = new ArrayList<StringBuilder>();
		outputOfMasking.add(masked_corrected);
		outputOfMasking.add(masked_quality);
		return outputOfMasking;
	}

	private PrintWriter writePacBio(String header, String original, String corrected, String quality, String combined, List<StringBuilder> maskResult,PrintWriter pw)
	{
		pw.println(header);
		pw.println(original);
		pw.println(corrected);
		pw.println(quality);
		pw.println(combined);
		pw.println(maskResult.get(0));
		pw.println(maskResult.get(1));
		pw.flush();
		return pw;
	}
	
}
